const { validateForeignKey } = require('../models/foreignKeyVis');
const { createService, removeService, updateService, findByIdService, findByPageService } = require('../services/blogService');
const { articleCountChange } = require('../services/blogTypeService');
const { removeByBlogIdService } = require('../services/messageService');
const AppError = require('../utils/AppError');
const Controller = require('../utils/Controller');
const { saveUtcDate, saveLocalDate } = require('../utils/moment');
const { handleTOC } = require('../utils/toc');
const { toi, to, sendResult } = require('../utils/tools');

class BlogTypeController extends Controller {
	async create(req, res, next) {
		req.body = handleTOC(req.body); // 通过Markdown得到文章目录
		req.body.createDate = saveUtcDate(req.body.createDate || new Date().getTime());
		req.body.toc = JSON.stringify(req.body.toc); // 接下来，我们将处理好的TOC格式转为字符串

		// const handlerInfo = handleTOC(req.body); // 通过Markdown得到文章目录
		// const blogInfo = {
		// 	...handlerInfo,
		// 	createDate: saveUtcDate(handlerInfo.createDate || new Date().getTime()),
		// 	toc: JSON.stringify(handlerInfo.toc) // 接下来，我们将处理好的TOC格式转为字符串
		// };

		// const serializeToc = handleTOC(req.body);
		// console.log(serializeToc);
		// const blogInfo = {
		// 	title: req.body.title,
		// 	description: req.body.description,
		// 	createDate: saveUtcDate(new Date().getTime()),
		// 	toc: JSON.stringify(serializeToc),
		// 	htmlContent: req.body.htmlContent,
		// 	thumb: req.body.thumb,
		// 	scanNumber: 0,
		// 	commentNumber: 0,
		// 	categoryId: req.body.categoryId
		// };

		const schema = req.joi.object({
			title: req.joi.string().required(),
			description: req.joi.string().required(),
			createDate: req.joi.date().required(),
			toc: req.joi.alternatives().try(
				req.joi.array(), // 可以是字符串
				req.joi.string() // 也可以是数字
			),
			htmlContent: req.joi.string().required(),
			thumb: req.joi.string().required(),
			scanNumber: req.joi.number(),
			commentNumber: req.joi.number(),
			categoryId: req.joi.number().external(validateForeignKey('blogType')).required()
		});
		const [failed] = await to(schema.validateAsync(req.body));
		if (failed) return next(new AppError(failed, 400));

		const [error, result] = await to(createService(req.body));
		if (error) return next(new AppError(failed, 400));

		await articleCountChange(req.body.categoryId);
		res.send(sendResult(result));
	}

	async remove(req, res, next) {
		// 通过单前文章id查询文章类型id
		const typeId = await getTypeId(req.params.id);
		if (typeId) {
			await articleCountChange(typeId, false); // 所属目录文章数减减
			await removeByBlogIdService(req.params.id); // 删除该文章所有评论
			// await commentCountChange(req.params.id, false, 0);
			await toi(removeService(req.params.id), res, next); // 最后删除
		} else {
			next(new AppError('文章或文章类型不存在', 400));
		}
	}

	async update(req, res, next) {
		// 首先判断正文内容有没有改变，因为正文内容的改变会影响 TOC
		if (req.body.htmlContent) {
			// 进入此 if，说明文章的正文内容有所改变，需要重新处理 TOC 目录
			req.body = handleTOC(req.body);
			// 接下来，我们将处理好的TOC格式转为字符串
			req.body.toc = JSON.stringify(req.body.toc);
		}

		const schema = req.joi.object({
			title: req.joi.string(),
			description: req.joi.string(),
			createDate: req.joi.date(),
			toc: req.joi.alternatives().try(
				req.joi.array(), // 可以是字符串
				req.joi.string() // 也可以是数字
			),

			htmlContent: req.joi.string(),
			thumb: req.joi.string(),
			scanNumber: req.joi.number(),
			commentNumber: req.joi.number(),
			categoryId: req.joi.number().external(validateForeignKey('blogType'))
		});
		if (req.body.toc != undefined) {
			req.body.toc = JSON.stringify(req.body.toc);
		}
		const [failed] = await to(schema.validateAsync(req.body));
		if (failed) return next(new AppError(failed, 400));

		// 校验类型id是否有变
		if (req.body.categoryId) {
			const typeId = await getTypeId(req.params.id);
			if (typeId != req.body.categoryId) {
				await articleCountChange(req.body.categoryId);
				await articleCountChange(typeId, false);
			}
		}

		await toi(updateService(req.body, req.params.id), res, next);
	}

	async findByPage(req, res, next) {
		const schema = req.joi
			.object({
				limit: req.joi.string().regex(/^\d+$/),
				page: req.joi.string().regex(/^\d+$/),
				title: req.joi.string(),
				categoryId: req.joi.string().regex(/^\d+$/)
			})
			.unknown(true);
		const { error: failed } = schema.validate(req.query);
		if (failed) return next(new AppError(failed, 401));

		await toi(findByPageService(req.query), res, next);
	}

	async findById(req, res, next) {
		await toi(findByIdService(req.params.id), res, next);
	}
}

/**
 * 通过文章id获取类型id
 * @param {*} id 文章id
 * @returns  类型id
 */
async function getTypeId(id) {
	const [blogErr, blogRes] = await to(findByIdService(id));
	if (blogErr) return;
	const typeId = blogRes?.category?.id;
	return typeId;
}

module.exports = new BlogTypeController();
